package yunjiao.javatutorials.guava.concurrent.timed;

import yunjiao.javatutorials.guava.concurrent.ForwardingCondition;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;

/**
 * 带超时监控的 Condition
 *
 * @author yangyunjiao
 */
public class TimedCondition extends ForwardingCondition {
    private final Condition delegate;
    private final AtomicLong totalWaitTime = new AtomicLong(0);
    private final AtomicLong waitCount = new AtomicLong(0);
    private final AtomicLong timeoutCount = new AtomicLong(0);

    public TimedCondition(Condition delegate) {
        this.delegate = delegate;
    }

    @Override
    protected Condition delegate() {
        return delegate;
    }

    @Override
    public boolean await(long time, TimeUnit unit) throws InterruptedException {
        long startTime = System.nanoTime();
        boolean result = super.await(time, unit);
        long endTime = System.nanoTime();

        long waitTime = endTime - startTime;
        totalWaitTime.addAndGet(waitTime);
        waitCount.incrementAndGet();

        if (!result) {
            timeoutCount.incrementAndGet();
        }

        System.out.printf("[TimedCondition] 等待完成: 耗时 %d ns, 结果: %s (超时: %s)%n",
                waitTime, result, !result);
        return result;
    }

    @Override
    public void await() throws InterruptedException {
        long startTime = System.nanoTime();
        super.await();
        long endTime = System.nanoTime();

        long waitTime = endTime - startTime;
        totalWaitTime.addAndGet(waitTime);
        waitCount.incrementAndGet();

        System.out.printf("[TimedCondition] 无限等待完成: 耗时 %d ns%n", waitTime);
    }

    @Override
    public void awaitUninterruptibly() {
        long startTime = System.nanoTime();
        super.awaitUninterruptibly();
        long endTime = System.nanoTime();

        long waitTime = endTime - startTime;
        totalWaitTime.addAndGet(waitTime);
        waitCount.incrementAndGet();

        System.out.printf("[TimedCondition] 不可中断等待完成: 耗时 %d ns%n", waitTime);
    }

    // 统计方法
    public double getAverageWaitTime() {
        long count = waitCount.get();
        return count == 0 ? 0 : (double) totalWaitTime.get() / count;
    }

    public long getTotalWaitCount() {
        return waitCount.get();
    }

    public long getTotalWaitTime() {
        return totalWaitTime.get();
    }

    public long getTimeoutCount() {
        return timeoutCount.get();
    }

    public double getTimeoutRate() {
        long count = waitCount.get();
        return count == 0 ? 0 : (double) timeoutCount.get() / count;
    }

    public void resetStatistics() {
        totalWaitTime.set(0);
        waitCount.set(0);
        timeoutCount.set(0);
        System.out.println("[TimedCondition] 统计信息已重置");
    }

    public void printStatistics() {
        System.out.println("=== TimedCondition 统计 ===");
        System.out.printf("总等待次数: %d%n", getTotalWaitCount());
        System.out.printf("总等待时间: %d ns%n", getTotalWaitTime());
        System.out.printf("平均等待时间: %.2f ns%n", getAverageWaitTime());
        System.out.printf("超时次数: %d%n", getTimeoutCount());
        System.out.printf("超时率: %.2f%%%n", getTimeoutRate() * 100);
    }
}
